package com.sihai.core;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.ResultTransformer;

/**
 * <code>CriteriaBuilder</code> 用于构建 {@link org.hibernate.Criteria} 对象
 */
public class DynamicCriteria {

	private Criteria criteria;

	public Criteria getCriteria() {
		return criteria;
	}

	public DynamicCriteria(Criteria criteria) {
		this.criteria = criteria;
	}

	public DynamicCriteria orEqIfNotNull(String property1, Object value1, String property2, Object value2) {
		if (value1 != null && value2 != null) {
			return this;
		}
		this.criteria.add(Restrictions.or(Restrictions.eq(property1, value1), Restrictions.eq(property2, value2)));
		return this;
	}

	public DynamicCriteria andEqIfNotEmpty(String property, String value) {
		if (StringUtils.isNotBlank(value)) {
			criteria.add(Restrictions.eq(property, StringUtils.trim(value)));
		}
		return this;
	}

	public DynamicCriteria andEqIfNotNull(String property, Object value) {
		if (value != null) {
			criteria.add(Restrictions.eq(property, value));
		}
		return this;
	}

	public DynamicCriteria andLikeIfNotEmpty(String property, String value, MatchMode matchMode) {
		if (StringUtils.isNotBlank(value)) {
			criteria.add(Restrictions.like(property, StringUtils.trimToEmpty(value), matchMode));
		}
		return this;
	}

	public DynamicCriteria andGeIfNotNull(String property, Object value) {
		if (value != null) {
			criteria.add(Restrictions.ge(property, value));
		}
		return this;
	}

	public DynamicCriteria andGtIfNotNull(String property, Object value) {
		if (value != null) {
			criteria.add(Restrictions.gt(property, value));
		}
		return this;
	}

	public DynamicCriteria andLeIfNotNull(String property, Object value) {
		if (value != null) {
			criteria.add(Restrictions.le(property, value));
		}
		return this;
	}

	public DynamicCriteria andLtIfNotNull(String property, Object value) {
		if (value != null) {
			criteria.add(Restrictions.lt(property, value));
		}
		return this;
	}

	//----------------- delegate method -----------------------

	public DynamicCriteria add(Criterion criterion) {
		criteria.add(criterion);
		return this;
	}

	public DynamicCriteria addOrder(Order order) {
		criteria.addOrder(order);
		return this;
	}

	public DynamicCriteria createAlias(String associationPath, String alias, int joinType) {
		criteria.createAlias(associationPath, alias, joinType);
		return this;
	}

	public DynamicCriteria createAlias(String associationPath, String alias) {
		criteria.createAlias(associationPath, alias);
		return this;
	}

	public DynamicCriteria createCriteria(String associationPath, int joinType) {
		return new DynamicCriteria(this.criteria.createCriteria(associationPath, joinType));
	}

	public DynamicCriteria createCriteria(String associationPath, String alias, int joinType) {
		return new DynamicCriteria(this.criteria.createCriteria(associationPath, alias, joinType));
	}

	public DynamicCriteria createCriteria(String associationPath, String alias) {
		return new DynamicCriteria(this.criteria.createCriteria(associationPath, alias));
	}

	public DynamicCriteria createCriteria(String associationPath) {
		return new DynamicCriteria(this.criteria.createCriteria(associationPath));
	}

	public String getAlias() {
		return criteria.getAlias();
	}

	public DynamicCriteria setComment(String comment) {
		criteria.setComment(comment);
		return this;
	}

	public DynamicCriteria setFetchMode(String associationPath, FetchMode mode) {
		criteria.setFetchMode(associationPath, mode);
		return this;
	}

	public DynamicCriteria setLockMode(LockMode lockMode) {
		criteria.setLockMode(lockMode);
		return this;
	}

	public DynamicCriteria setLockMode(String alias, LockMode lockMode) {
		criteria.setLockMode(alias, lockMode);
		return this;
	}

	public DynamicCriteria setProjection(Projection projection) {
		criteria.setProjection(projection);
		return this;
	}

	public DynamicCriteria setResultTransformer(ResultTransformer resultTransformer) {
		criteria.setResultTransformer(resultTransformer);
		return this;
	}
}
